package pl.jtb.ctl.tabory.dao.impl.mybatis.servicemanager;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;

import pl.jtb.ctl.tabory.dao.api.services.ICompositionService;
import pl.jtb.ctl.tabory.dao.api.services.IServiceManager;
import pl.jtb.ctl.tabory.dao.api.services.IStationService;
import pl.jtb.ctl.tabory.dao.api.services.ITripService;
import pl.jtb.ctl.tabory.dao.api.services.IUserRoleService;
import pl.jtb.ctl.tabory.dao.api.services.IUserService;
import pl.jtb.ctl.tabory.dao.api.services.IVagonService;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.CompositionServiceImpl;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.StationSerivceImpl;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.TripServiceImpl;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.UserRoleServiceImpl;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.UserServiceImpl;
import pl.jtb.ctl.tabory.dao.impl.mybatis.impl.VagonServiceImpl;

public class ServiceManager implements IServiceManager {

    private final static Logger logger = Logger.getLogger(ServiceManager.class);

    private static SqlSessionFactory sqlSessionFactory;

    private static Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

    private static ServiceManager instance;

    public static ServiceManager getInstance() throws IOException {
        logger.debug("Retrieving instance of ServiceManager");
        if (instance == null) {
            instance = new ServiceManager();
        }
        return instance;
    }

    private ServiceManager() throws IOException {
        initialize();
    }

    private static void initialize() throws IOException {
        logger.debug("Initializing Service Manager...");
        logger.debug("Creating Reader to read xml configuration...");
        String resource = "resources/mybatis-cofnig.xml";
        Reader reader = Resources.getResourceAsReader(resource);
        logger.debug("Builder SQL Session Factory from reader...");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        if (sqlSessionFactory != null) {
            UserRoleServiceImpl userRoleService = new UserRoleServiceImpl(sqlSessionFactory);
            UserServiceImpl userServiceImpl = new UserServiceImpl(sqlSessionFactory);
            VagonServiceImpl vagonServiceImpl = new VagonServiceImpl(sqlSessionFactory);
            CompositionServiceImpl compositionServiceImpl = new CompositionServiceImpl(sqlSessionFactory);
            StationSerivceImpl stationSerivceImpl = new StationSerivceImpl(sqlSessionFactory);
            TripServiceImpl tripServiceImpl = new TripServiceImpl(sqlSessionFactory);
            map.put(IUserRoleService.class, userRoleService);
            map.put(IUserService.class, userServiceImpl);
            map.put(IVagonService.class, vagonServiceImpl);
            map.put(ICompositionService.class, compositionServiceImpl);
            map.put(IStationService.class, stationSerivceImpl);
            map.put(ITripService.class, tripServiceImpl);
            logger.debug("Service Manager initialized.");
        }
    }

    @Override
    public IUserRoleService getUserRoleService() throws Exception {
        logger.debug("Retrieving IUserRoleService.");
        IUserRoleService service = (IUserRoleService) map.get(IUserRoleService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev IUserRoleService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

    @Override
    public IUserService getUserService() throws Exception {
        logger.debug("Retrieving IUserService.");
        IUserService service = (IUserService) map.get(IUserService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev IUserService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

    @Override
    public IVagonService getVagonService() throws Exception {
        logger.debug("Retrieving IVagonService.");
        IVagonService service = (IVagonService) map.get(IVagonService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev IVagonService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

    @Override
    public ICompositionService getCompositionService() throws Exception {
        logger.debug("Retrieving ICompositionService.");
        ICompositionService service = (ICompositionService) map.get(ICompositionService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev ICompositionService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

    @Override
    public IStationService getStationService() throws Exception {
        logger.debug("Retrieving IStationService.");
        IStationService service = (IStationService) map.get(IStationService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev IStationService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

    @Override
    public ITripService getTripService() throws Exception {
        logger.debug("Retrieving ITripService.");
        ITripService service = (ITripService) map.get(ITripService.class);
        if (service == null) {
            Exception exception = new Exception("Could not retriev ITripService");
            exception.fillInStackTrace();
            throw exception;
        }
        return service;
    }

}
